Skip to content

fix: don't intercept forms without explicit f-partial inside f-client-nav#3722

Merged
bartlomieju merged 3 commits into
mainfrom
fix/form-partial-interception
Mar 29, 2026
Merged

fix: don't intercept forms without explicit f-partial inside f-client-nav#3722
bartlomieju merged 3 commits into
mainfrom
fix/form-partial-interception

Conversation

@bartlomieju

Copy link
Copy Markdown
Contributor

Summary

  • Fixes Partial "messages" not found. Skipping... #3473 — "Partial 'messages' not found. Skipping..."
  • Forms inside f-client-nav without an explicit f-partial attribute were being intercepted as partial requests, breaking normal form submissions

Root cause

The form submit handler's fallback chain for determining the partial URL:

const rawPartialUrl = e.submitter?.getAttribute(PARTIAL_ATTR) ??
  e.submitter?.getAttribute("formaction") ??
  el.getAttribute(PARTIAL_ATTR) ?? el.action;

Always falls through to el.action, which defaults to the current page URL for any <form> without an explicit action attribute. Since el.action is never empty, the rawPartialUrl !== "" check on the next line was always true, meaning every form inside f-client-nav was intercepted — even forms that never opted in to partial navigation.

This caused:

  1. Normal form POSTs to be sent with ?fresh-partial=true
  2. Server rendering in partial mode, returning only <Partial> fragments
  3. The rest of the page content being lost

Fix

Added a hasExplicitPartial check that requires the form or its submitter to have an explicit f-partial or formaction attribute before intercepting. Forms without these attributes now submit normally, even inside f-client-nav.

Test plan

  • Lint/format clean
  • Manual test: form inside f-client-nav without f-partial should submit normally (full page reload)
  • Manual test: form with f-partial inside f-client-nav should still work as partial navigation

🤖 Generated with Claude Code

bartlomieju and others added 2 commits March 28, 2026 09:51
…-nav (#3473)

Forms inside f-client-nav were always intercepted as partial requests
because the fallback chain for rawPartialUrl ended with el.action,
which is always non-empty (defaults to the current URL). This caused
normal forms without f-partial to be sent with ?fresh-partial=true,
breaking forms that expect a full page re-render after POST.

Now only forms (or submitters) with an explicit f-partial or
formaction attribute are intercepted for partial navigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ception

Forms with an explicit `action` attribute inside `f-client-nav` should
still be intercepted as partials. Only forms *without* any of
`f-partial`, `formaction`, or `action` attributes are left alone.

Add test for forms without action inside f-client-nav to verify they
submit normally without partial interception.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bartlomieju bartlomieju enabled auto-merge (squash) March 29, 2026 18:56
The test for non-intercepted form submission was racing against the
browser's full page navigation. Use Promise.all with
waitForNavigation() to properly wait for the POST response before
checking for the .submitted element.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bartlomieju bartlomieju merged commit dd1ecf3 into main Mar 29, 2026
7 of 9 checks passed
@bartlomieju bartlomieju deleted the fix/form-partial-interception branch March 29, 2026 19:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Partial "messages" not found. Skipping...

1 participant